﻿using log4net.Appender;
using log4net.Core;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Net;
using System.Linq;

namespace log4net.extension.mongo
{
    public abstract class MongoAppenderBase : AppenderSkeleton
    {
        protected IMongoClient m_mongoClient = null;
        protected string m_localIp = null;

        public MongoAppenderBase()
        {
            this.DatabaseName = "LogDB";
            this.CollectinName = "LogCollection";
        }

        public override void ActivateOptions()
        {
            base.ActivateOptions();
            MongoClientSettings setting = MongoClientSettings.FromUrl(new MongoUrl(ConnectionString));
            setting.MaxConnectionPoolSize = 200;
            setting.ConnectTimeout = TimeSpan.FromSeconds(1);
            setting.ServerSelectionTimeout = TimeSpan.FromSeconds(1);
            setting.WriteConcern = WriteConcern.Unacknowledged;
            m_mongoClient = new MongoClient(setting);
            m_localIp = GetLocalIp();
        }

        protected override void Append(LoggingEvent loggingEvent)
        {
            try
            {
                if (m_mongoClient == null) return;
                var db = m_mongoClient.GetDatabase(this.DatabaseName).GetCollection<BsonDocument>(this.CollectinName);
                var log = Convert(loggingEvent);
                if (log != null)
                    db.InsertOne(log);
            }
            catch (Exception ex)
            {
                ErrorHandler.Error("Exception while writing to mongo db", ex);
            }
        }
        private string GetLocalIp()
        {
            var ipArray = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
            if (ipArray != null && ipArray.Length > 0)
            {
                var ip4 = ipArray.FirstOrDefault(p => p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
                if (ip4 != null)
                {
                    return ip4.ToString();
                }
            }
            return string.Empty;
        }

        protected abstract BsonDocument Convert(LoggingEvent loggingEvent);

        #region Property

        public string DatabaseName { get; set; }
        public string CollectinName { get; set; }
        public string ConnectionString { get; set; }

        #endregion
    }
}
